package com.soup.hummingbird.module.threadpool;

import cn.hutool.core.exceptions.ExceptionUtil;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import lombok.extern.slf4j.Slf4j;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 〈对 {@link ThreadPoolExecutor }进行增强〉<br>
 *     1. 构造方法 {@link ThreadPoolExecutor#ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue, java.util.concurrent.ThreadFactory, java.util.concurrent.RejectedExecutionHandler)}
 *        的增强，将实例对象放到集合中，这个集合是弱应用，便于定时采集功能获取线程池对象的运行状况
 *     2. 对某些方法进行增强
 *
 * @author zhaoyi
 */
@Slf4j
public class ThreadPoolExecutorTransformer implements ClassFileTransformer {
    private static final Set<String> classNameSet = new HashSet<>();

    static {
        classNameSet.add("java.util.concurrent.ThreadPoolExecutor");
    }

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        String currentClassName = className.replaceAll("/", ".");
        if (!classNameSet.contains(currentClassName)) {
            return null;
        }

        log.info("start transform class: {}", currentClassName);

        try {
            CtClass ctClass = ClassPool.getDefault().get(currentClassName);
            CtConstructor constructor = ctClass.getConstructor("(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;Ljava/util/concurrent/ThreadFactory;Ljava/util/concurrent/RejectedExecutionHandler;)V");
            // log.info("constructor: {}", constructor.getLongName());
            // enhanceConstructor(constructor);

            CtConstructor[] constructors = ctClass.getDeclaredConstructors();
            for (CtConstructor ctc : constructors) {
                enhanceConstructor(ctc);
            }

        } catch (Exception e) {
            log.error("enhance constructor method occur error: {}", e);
        }


        return null;
    }

    private void enhanceConstructor(CtConstructor constructor) throws Exception {
        if (constructor.isEmpty()) {
            log.error("Constructor method is empty");
            return;
        }

        // final StringBuilder body = new StringBuilder();
        // body.append("{System.out.print(\" =====> 构造方法调用结束 \");}");
        // constructor.setBody(body.toString());

        constructor.insertAfter("System.out.print(\" =====> 构造方法调用结束 \");");

        /*final StringBuilder source = new StringBuilder();
        source.append("{")
                .append("$_ = $proceed($$);").append("\n") //调用原有代码，类似于method();($$)表示所有的参数
                .append("System.out.print(\" =====> return: \" + $0);").append("\n")
                .append("}");

        ExprEditor editor = new ExprEditor() {
            @Override
            public void edit(MethodCall methodCall) throws CannotCompileException {
                methodCall.replace(source.toString());
            }
        };
        constructor.instrument(editor);*/
    }
}
